﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CkSoftware.GroupMe.Sdk.Core.Dao;
using CkSoftware.GroupMe.Sdk.Messaging;

namespace CkSoftware.GroupMe.Sdk.Helpers.Emoji
{
	/// <summary>
	/// Provides static methods to parse a message containing emoji definitions
	/// </summary>
	public static class GroupMeEmojiMessageParser
	{
		/// <summary>
		/// The character which is used to replace the messages.
		/// </summary>
		public const char MessageReplaceCharacter = '�';

		private const string DefaultEmojiSearchRegex = @"{{(\d*),(\d*)}}";

		/// <summary>
		/// Creates a new message and fills up the emoji attachment automatically.
		/// </summary>
		/// <param name="messageHandler">The <see cref="GroupMeMessages" /> handler for sending a message.</param>
		/// <param name="sourceGuid">
		/// The sourceGuid of this message. This is an identifier of this message and should be unique, to
		/// correctly identify duplicate submits.
		/// </param>
		/// <param name="text">The text to submit.</param>
		/// <param name="emojiSearchRegexString">
		/// A regex to search for emoji elements in the message. The regex must result in 2
		/// groups where the first group contains the pack id and the second contains the emoji id of the pack. Default search
		/// regex looks for this scheme: {{PACKID,EMOJIID}}. Example: {{1,0}} = first image of first pack, {{3,10}} = 10th image of
		/// 3rd pack.
		/// </param>
		/// <param name="attachments">A list of attachments to add to this mesasge.</param>
		/// <returns>The created message-data.</returns>
		public static async Task<GroupMeMessageData> CreateMessageWithEmojiImages(GroupMeMessages messageHandler,
			string sourceGuid, string text, string emojiSearchRegexString = DefaultEmojiSearchRegex,
			IEnumerable<GroupMeAttachmentBase> attachments = null)
		{
			var attachmentCollection = new List<GroupMeAttachmentBase>(attachments ?? Enumerable.Empty<GroupMeAttachmentBase>());

			GroupMeEmojiAttachment attachment;
			string replacedMessage = ParseMessage(text, out attachment);

			if (attachment != null && attachment.EmojiMap != null && attachment.EmojiMap.Any())
			{
				attachmentCollection.Add(attachment);
			}

			return await messageHandler.CreateMessage(sourceGuid, replacedMessage, attachmentCollection);
		}

		/// <summary>
		/// Parses the given message using the given emojiSearchRegexString and returns the correct replaced message and as out
		/// parameter the <see cref="GroupMeEmojiAttachment" /> to attach to the message create method.
		/// </summary>
		/// <param name="message">The text to submit.</param>
		/// <param name="emojiAttachment">
		/// Output of the parsed emoji images, can be directly added to the message attachments. Will
		/// be null if there is no emoji in the message.
		/// </param>
		/// <param name="emojiSearchRegexString">
		/// A regex to search for emoji elements in the message. The regex must result in 2
		/// groups where the first group contains the pack id and the second contains the emoji id of the pack. Default search
		/// regex looks for this scheme: {{PACKID,EMOJIID}}. Example: {{1,0}} = first image of first pack, {{3,10}} = 10th image of
		/// 3rd pack.
		/// </param>
		/// <returns>The replaced message, ready to send along with the generated <see cref="GroupMeEmojiAttachment" />.</returns>
		public static string ParseMessage(string message, out GroupMeEmojiAttachment emojiAttachment,
			string emojiSearchRegexString = DefaultEmojiSearchRegex)
		{
			var emojiDefinitions = new List<GroupMeEmojiDefinition>();
			var regex = new Regex(emojiSearchRegexString, RegexOptions.Compiled | RegexOptions.Multiline);

			string replacedMessage = regex.Replace(message, match =>
			{
				emojiDefinitions.Add(new GroupMeEmojiDefinition
				{
					PackId = Convert.ToInt32(match.Groups[1].Value),
					EmojiId = Convert.ToInt32(match.Groups[2].Value)
				});

				return MessageReplaceCharacter.ToString(CultureInfo.CurrentCulture);
			});

			if (emojiDefinitions.Any())
			{
				emojiAttachment = new GroupMeEmojiAttachment
				{
					EmojiPlaceholder = MessageReplaceCharacter,
					EmojiMap = emojiDefinitions
				};
			}
			else
			{
				emojiAttachment = null;
			}

			return replacedMessage;
		}
	}
}